﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Query;

namespace Devonline.Identity.Admin.Controllers;

/// <summary>
/// 资源管理
/// </summary>    
[Route("api/[controller]")]
[ApiController]
[SecurityHeaders]
[Authorize(Roles = GROUP_MAINTAINERS)]
public class ResourcesController : ControllerBase
{
    private readonly string _userName;
    private readonly ILogger<ResourcesController> _logger;
    private readonly ResourceAccessStore _resourceAccessStore;
    private readonly IDataService<IdentityDbContext, Resource> _dataService;
    private static CancellationToken CancellationToken => CancellationToken.None;

    public ResourcesController(
        IDataService<IdentityDbContext, Resource> dataService,
        ResourceAccessStore resourceAccessStore,
        ILogger<ResourcesController> logger,
        IHttpContextAccessor httpContextAccessor
        )
    {
        _dataService = dataService;
        _resourceAccessStore = resourceAccessStore;
        _logger = logger;
        _userName = httpContextAccessor.HttpContext.User.Identity.Name;
    }

    [HttpGet, EnableQuery]
    public IActionResult Get() => Ok(_dataService.GetQueryable());

    [HttpPost]
    public async Task<IActionResult> CreateAsync(ResourceViewModel viewModel) => Ok(await _dataService.AddAsync<ResourceViewModel, Attachment>(viewModel, default));

    [HttpPut]
    public async Task<IActionResult> UpdateAsync(ResourceViewModel viewModel) => Ok(await _dataService.UpdateAsync<ResourceViewModel, Attachment>(viewModel, default, false));

    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteAsync(string id)
    {
        await _dataService.DeleteAsync<ResourceViewModel, Attachment>(id, default, false);
        return Ok();
    }

    /// <summary>
    /// 修改资源父级
    /// </summary>
    /// <param name="viewModel"></param>
    /// <returns></returns>
    [HttpPost("ChangeParent")]
    public async Task<IActionResult> ChangeParentAsync(ChangeParentViewModel viewModel)
    {
        _logger.LogInformation("user {user} will change the resource {resource} parent to {parent}", _userName, viewModel.Id, viewModel.ParentId);
        var resource = await _dataService.GetAsync(viewModel.Id);
        if (resource == null)
        {
            return NotFound();
        }

        try
        {
            await _resourceAccessStore.SetParent(resource, viewModel.ParentId);
            _dataService.Update(resource);
            await _dataService.SaveChangesAsync();
            _logger.LogWarning("user {user} success to change the resource {resource} parent to {parent}", _userName, resource.Name, viewModel.ParentId);
            return Ok();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "user {user} change the resource {resource} parent to {parent} throw exception", _userName, resource.Name, viewModel.ParentId);
        }

        return BadRequest($"修改资源 {resource.Name} 父级没有成功!");
    }
    /// <summary>
    /// 修改资源所有者
    /// </summary>
    /// <param name="viewModel"></param>
    /// <returns></returns>
    [HttpPost("ChangeOwner")]
    public async Task<IActionResult> ChangeOwnerAsync(ChangeOwnerViewModel viewModel)
    {
        _logger.LogInformation("user {user} will change the resource {resource} owner to {owner} and owner type to {ownerType}", _userName, viewModel.Id, viewModel.OwnerId, viewModel.IdentityType);
        var resource = await _dataService.GetAsync(viewModel.Id);
        if (resource == null)
        {
            return NotFound();
        }
        try
        {
            await _resourceAccessStore.SetOwner(resource, viewModel.OwnerId);
            _dataService.Update(resource);
            await _dataService.SaveChangesAsync();
            _logger.LogWarning("user {user} success to change the resource {resource} owner to {owner} and owner type to {ownerType}", _userName, resource.Name, viewModel.OwnerId, viewModel.IdentityType);
            return Ok();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "user {user} change the resource {resource} owner to {owner} and owner type to {ownerType} throw exception", _userName, resource.Name, viewModel.OwnerId, viewModel.IdentityType);
        }

        return BadRequest($"修改资源 {resource.Name} 所有者没有成功!");
    }
    /// <summary>
    /// 修改资源可访问级别
    /// </summary>
    /// <param name="viewModel"></param>
    /// <returns></returns>
    [HttpPost("ChangeLevel")]
    public async Task<IActionResult> ChangeLevelAsync(ResourceChangeLevelViewModel viewModel)
    {
        _logger.LogInformation("user {user} will change the resource {resource} level to {level} and access level to {accessLevel}", _userName, viewModel.Id, viewModel.LevelName, viewModel.AccessLevel);
        var resource = await _dataService.GetAsync(viewModel.Id);
        if (resource == null)
        {
            return NotFound();
        }
        try
        {
            await _resourceAccessStore.SetLevel(resource, viewModel.LevelName, CancellationToken);
            await _resourceAccessStore.SetAccessLevel(resource, viewModel.AccessLevel, CancellationToken);
            _dataService.Update(resource);
            await _dataService.SaveChangesAsync();
            _logger.LogWarning("user {user} success to change the resource {resource} level to {level} and access level to {accessLevel}", _userName, resource.Name, viewModel.LevelName, viewModel.AccessLevel);
            return Ok();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "user {user} change the resource {resource} level to {level} and access level to {accessLevel} throw exception", _userName, resource.Name, viewModel.LevelName, viewModel.AccessLevel);
        }

        return BadRequest($"修改资源 {resource.Name} 级别没有成功!");
    }
}